using MediatR;
using Microsoft.Extensions.Logging;
using RBAC.Domain.MaterialManage;
using RBAC.Domain.SalesManage;
using RBAC.ErrorCode;
using RBAC.Interstructrue.Base;
using RBAC.Write.Api.Application.Command.ERP.SalesManagement;
using System.Transactions;

namespace RBAC.Write.Api.Application.Handler.ERP.SalesManagement
{
    /// <summary>
    /// 编辑销售订单处理器
    /// </summary>
    public class UpdateSalesOrderHandler : IRequestHandler<UpdateSalesOrderCommand, APIResult<bool>>
    {
        private readonly IBaseRepository<SalesOrder> salesOrderRepository;
        private readonly IBaseRepository<SalesOrderDetail> salesOrderDetailRepository;
        private readonly IBaseRepository<Mater> materRepository;
        private readonly ILogger<UpdateSalesOrderHandler> logger;

        public UpdateSalesOrderHandler(
            IBaseRepository<SalesOrder> salesOrderRepository,
            IBaseRepository<SalesOrderDetail> salesOrderDetailRepository,
            IBaseRepository<Mater> materRepository,
            ILogger<UpdateSalesOrderHandler> logger)
        {
            this.salesOrderRepository = salesOrderRepository;
            this.salesOrderDetailRepository = salesOrderDetailRepository;
            this.materRepository = materRepository;
            this.logger = logger;
        }

        /// <summary>
        /// 处理编辑销售订单请求
        /// </summary>
        /// <param name="request">编辑请求</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>编辑结果</returns>
        public Task<APIResult<bool>> Handle(UpdateSalesOrderCommand request, CancellationToken cancellationToken)
        {
            APIResult<bool> result = new APIResult<bool>();

            try
            {
                logger.LogInformation("开始编辑销售订单，订单ID：{OrderId}，客户名称：{CustomerName}，明细数量：{DetailCount}",
                    request.Id, request.CustomerName, request.Details.Count);

                // 1. 数据验证
                if (!ValidateRequest(request, out string validationMessage))
                {
                    result.Code = APIEnums.Error;
                    result.Msg = validationMessage;
                    logger.LogWarning("销售订单数据验证失败：{Message}", validationMessage);
                    return Task.FromResult(result);
                }

                // 2. 检查销售订单是否存在
                var salesOrder = salesOrderRepository.GetModel(request.Id);
                if (salesOrder == null)
                {
                    result.Code = APIEnums.Error;
                    result.Msg = "销售订单不存在或已被删除";
                    logger.LogWarning("销售订单不存在或已被删除，ID：{OrderId}", request.Id);
                    return Task.FromResult(result);
                }

                // 3. 检查订单状态，只有开立状态的订单才能编辑
                if (salesOrder.OrderStatus != "开立")
                {
                    result.Code = APIEnums.Error;
                    result.Msg = "只有开立状态的销售订单才能编辑";
                    logger.LogWarning("非开立状态的销售订单不能编辑，ID：{OrderId}，当前状态：{Status}", request.Id, salesOrder.OrderStatus);
                    return Task.FromResult(result);
                }

                // 4. 验证物料是否存在
                var materIds = request.Details.Select(d => d.MaterId).Distinct().ToList();
                var existingMaters = materRepository.GetAll($"Id IN ({string.Join(",", materIds.Select((_, i) => $"@Id{i}"))})",
                    materIds.Select((id, i) => new { Key = $"@Id{i}", Value = (object)id }).ToDictionary(x => x.Key, x => x.Value));

                if (existingMaters.Count != materIds.Count)
                {
                    var missingMaterIds = materIds.Except(existingMaters.Select(m => m.Id)).ToList();
                    result.Code = APIEnums.Error;
                    result.Msg = $"以下物料ID不存在：{string.Join(", ", missingMaterIds)}";
                    logger.LogWarning("销售订单编辑失败，物料不存在，物料ID：{MaterIds}", string.Join(", ", missingMaterIds));
                    return Task.FromResult(result);
                }

                // 使用事务确保数据一致性
                using (TransactionScope transaction = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }))
                {
                    try
                    {
                        // 5. 更新销售订单主信息
                        salesOrder.OrderType = request.OrderType;
                        salesOrder.OrderDate = request.OrderDate;
                        salesOrder.BusinessType = request.BusinessType;
                        salesOrder.BusinessStatus = request.BusinessStatus;
                        salesOrder.SalesDepartment = request.SalesDepartment;
                        salesOrder.SalesPersonId = request.SalesPersonId;
                        salesOrder.SalesPerson = request.SalesPerson;
                        salesOrder.SalesChannel = request.SalesChannel;
                        salesOrder.SupplyMode = request.SupplyMode;
                        salesOrder.CustomerName = request.CustomerName;
                        salesOrder.Receiver = request.Receiver;
                        salesOrder.Phone = request.Phone;
                        salesOrder.Address = request.Address;
                        salesOrder.DestinationCountry = request.DestinationCountry;
                        salesOrder.ContractNo = request.ContractNo;
                        salesOrder.PaymentTerms = request.PaymentTerms;
                        salesOrder.DeliveryDate = request.DeliveryDate;
                        salesOrder.DeliveryStatus = request.DeliveryStatus;
                        salesOrder.Remark = request.Remark;

                        var updateResult = salesOrderRepository.Update(salesOrder);
                        if (updateResult <= 0)
                        {
                            throw new InvalidOperationException("销售订单主信息更新失败");
                        }
                        logger.LogInformation("销售订单主信息更新成功，ID：{SalesOrderId}", salesOrder.Id);

                        // 6. 获取现有明细
                        var existingDetails = salesOrderDetailRepository.GetAll("SalesOrderId = @SalesOrderId AND IsDeleted = false",
                            new { SalesOrderId = request.Id });

                        // 7. 逻辑删除所有现有明细
                        if (existingDetails.Any())
                        {
                            logger.LogInformation("开始删除销售订单原有明细，数量：{DetailCount}", existingDetails.Count);

                            foreach (var detail in existingDetails)
                            {
                                detail.IsDeleted = true;
                                var detailUpdateResult = salesOrderDetailRepository.Update(detail);
                                if (detailUpdateResult <= 0)
                                {
                                    throw new InvalidOperationException($"销售订单明细删除失败，ID：{detail.Id}");
                                }
                            }

                            logger.LogInformation("销售订单原有明细删除成功，数量：{DetailCount}", existingDetails.Count);
                        }

                        // 8. 创建新的销售订单明细
                        var salesOrderDetails = new List<SalesOrderDetail>();
                        foreach (var detailCommand in request.Details)
                        {
                            var salesOrderDetail = new SalesOrderDetail
                            {
                                SalesOrderId = request.Id,
                                MaterId = detailCommand.MaterId,
                                Num = detailCommand.Num,
                                Price = detailCommand.Price,
                                Remark = detailCommand.Remark,
                                CreateTime = DateTime.Now,
                                CreateUser = "system", // 这里应该从当前用户上下文获取
                                IsDeleted = false
                            };
                            salesOrderDetails.Add(salesOrderDetail);
                        }

                        // 9. 批量保存新的销售订单明细
                        if (salesOrderDetails.Any())
                        {
                            var detailResult = salesOrderDetailRepository.CreateBatch(salesOrderDetails);
                            if (detailResult != salesOrderDetails.Count)
                            {
                                throw new InvalidOperationException($"销售订单明细创建失败：预期 {salesOrderDetails.Count} 条，实际创建 {detailResult} 条");
                            }
                            logger.LogInformation("销售订单新明细创建成功，数量：{DetailCount}", salesOrderDetails.Count);
                        }

                        // 提交事务
                        transaction.Complete();

                        result.Code = APIEnums.Success;
                        result.Data = true;
                        result.Msg = "销售订单编辑成功";
                        logger.LogInformation("销售订单编辑成功，ID：{OrderId}", request.Id);
                    }
                    catch (Exception ex)
                    {
                        // 事务会自动回滚
                        logger.LogError(ex, "销售订单编辑过程中发生错误，ID：{OrderId}，错误信息：{Message}", request.Id, ex.Message);
                        throw; // 重新抛出异常，让外层捕获
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "销售订单编辑失败，ID：{OrderId}，错误信息：{Message}", request.Id, ex.Message);
                result.Code = APIEnums.Error;
                result.Msg = $"销售订单编辑失败：{ex.Message}";
                result.Data = false;
            }

            return Task.FromResult(result);
        }

        /// <summary>
        /// 验证请求数据
        /// </summary>
        /// <param name="request">请求数据</param>
        /// <param name="message">验证消息</param>
        /// <returns>验证结果</returns>
        private bool ValidateRequest(UpdateSalesOrderCommand request, out string message)
        {
            message = string.Empty;

            if (request.Id <= 0)
            {
                message = "销售订单ID无效";
                return false;
            }

            if (string.IsNullOrWhiteSpace(request.CustomerName))
            {
                message = "客户名称不能为空";
                return false;
            }

            if (request.Details == null || !request.Details.Any())
            {
                message = "销售订单明细不能为空";
                return false;
            }

            foreach (var detail in request.Details)
            {
                if (detail.MaterId <= 0)
                {
                    message = "物料ID无效";
                    return false;
                }

                if (detail.Num <= 0)
                {
                    message = "数量必须大于0";
                    return false;
                }

                if (detail.Price < 0)
                {
                    message = "单价不能为负数";
                    return false;
                }
            }

            return true;
        }
    }
}
